package com.gzs.learn.payment.pay.action;

import cn.felord.payment.wechat.v3.WechatApiProvider;
import cn.felord.payment.wechat.v3.WechatPayCallback;
import com.gzs.learn.common.util.SpringContextUtil;
import com.gzs.learn.inf.BaseResponseDto;
import com.gzs.learn.payment.pay.ContextBase;
import com.gzs.learn.payment.pay.PaymentContext;
import com.gzs.learn.payment.pay.PaymentTypeEnum;
import com.gzs.learn.payment.pay.consumer.WechatTransactionCallbackConsumer;
import com.gzs.learn.payment.pay.context.PaymentCallbackContext;
import com.gzs.learn.payment.pay.notify.NotifyTypeEnum;
import com.gzs.learn.payment.pay.notify.PaymentNotify;
import com.gzs.learn.payment.pay.notify.event.OrderNotifyEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author zhisong.guan
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class PaymentCallbackAction extends BaseAction {
    private final WechatTransactionCallbackConsumer wechatTransactionCallbackConsumer;

    private final PaymentNotify paymentNotify;

    @Override
    public BaseResponseDto<?> executeAction(PaymentContext<ContextBase> context) {
        PaymentTypeEnum paymentTypeEnum = context.getPaymentTypeEnum();
        PaymentCallbackContext callbackContext = (PaymentCallbackContext) context.getContextObject();
        BaseResponseDto<?> responseDto = null;
        switch (paymentTypeEnum) {
            case ALIPAY:
                responseDto = alipayCallback(context);
                break;
            case WECHAT:
                responseDto = wechatCallback(context);
                break;
            case UNIONPAY:
                responseDto = unionpayCallback(context);
                break;
            default:
                break;
        }
        // 执行支付完成的回调通知,通知订单系统订单支付完成
        if (BaseResponseDto.isSuccess(responseDto)) {
            OrderNotifyEvent event = buildOrderNotifyEvent(callbackContext);
            paymentNotify.post(event);
        }
        return responseDto;
    }

    protected BaseResponseDto<?> wechatCallback(PaymentContext<ContextBase> context) {
        Integer channel = context.getContextObject().getChannel();
        WechatApiProvider provider = SpringContextUtil.getBean(WechatApiProvider.class);
        if (provider == null) {
            log.error("can not find wechat api provider");
            return BaseResponseDto.bizError("wechat api instance not found");
        }
        WechatPayCallback wechatPayCallback = provider.callback(String.valueOf(channel));
        if (wechatPayCallback == null) {
            log.error("can not find wechat callback");
            return BaseResponseDto.bizError("wechat callback instance not found");
        }
        PaymentCallbackContext callbackContext = (PaymentCallbackContext) context.getContextObject();
        Map<String, String> result = wechatPayCallback.transactionCallback(callbackContext.getWechatCallBackData(),
                wechatTransactionCallbackConsumer);
        return BaseResponseDto.success(result);
    }

    protected BaseResponseDto<?> alipayCallback(PaymentContext<ContextBase> context) {
        return BaseResponseDto.success("success");
    }

    protected BaseResponseDto<?> unionpayCallback(PaymentContext<ContextBase> context) {
        return BaseResponseDto.success("success");
    }

    protected OrderNotifyEvent buildOrderNotifyEvent(PaymentCallbackContext callbackContext) {
        OrderNotifyEvent orderNotifyEvent = new OrderNotifyEvent();
        orderNotifyEvent.setSerial(callbackContext.getSerial());
        orderNotifyEvent.setNotifyType(NotifyTypeEnum.PAYMENT.toString());
        orderNotifyEvent.setAmt(callbackContext.getAmt());
        orderNotifyEvent.setOrderId(callbackContext.getOrderId());
        orderNotifyEvent.setOrderFrom(callbackContext.getOrderFrom().getCode());
        orderNotifyEvent.setPaymentStatus(callbackContext.getStatus());
        return orderNotifyEvent;
    }

}
